﻿#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <mysql/mysql.h>
#include "cJSON.h"
#define LOCAL_IP  "192.168.0.186"
#define LOCAL_PORT 9876

//请假结构体
typedef struct leaveinfo
{
	char type[20];
	char name[20];
	char leavetime[20]; 
	char backtime[20];
	char leavecause[100];
	char approval_status[20];
}LEAVE;
/*
函数功能：解包至请假结构体
函数参数：LEAVE *leave-请假结构体
函数返回值：char *
*/
char * unLeavePack(LEAVE *leave);
/*
函数功能：服务器查询未被审核的请假信息并发送至客户端
函数参数：MYSQL mysql-数据库，int client_sock-客户端套接字
函数返回值：void
*/
void ServeApprovalLeave(MYSQL mysql,int client_sock);
/*
函数功能：服务器按照姓名查询请假信息并发送至客户端
函数参数：LEAVE leave-请假结构体MYSQL mysql-数据库，int client_sock-客户端套接字
函数返回值：int
*/
int ServeChecLeaveName(LEAVE leave,MYSQL mysql,int client_sock);
/*
函数功能：服务器按照时间查询请假信息并发送至客户端
函数参数：LEAVE leave-请假结构体MYSQL mysql-数据库，int client_sock-客户端套接字
函数返回值：void
*/
void ServeChecLeaveTime(LEAVE leave,MYSQL mysql,int client_sock);
/*
函数功能：服务器修改用户未被审批的请假信息
函数参数：LEAVE leave-请假结构体MYSQL mysql-数据库，int client_sock-客户端套接字
函数返回值：int
*/
int UpdateLeaveMyself(LEAVE leave,MYSQL mysql,int client_sock);

char p[1024] = {0};
int main(int argc,const char* argv[])
{
	int sc = socket(AF_INET,SOCK_STREAM,0);

	if(sc == -1)
	{
		perror("socket");
		return -1;
	}

	struct sockaddr_in saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(LOCAL_PORT);
	saddr.sin_addr.s_addr = inet_addr(LOCAL_IP);

	int optval = 1;
	//bind 的地址允许重复使用
	//设置sock状态
	setsockopt(sc,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
	int ret = bind(sc,(struct sockaddr*)&saddr,sizeof(saddr));
	if(ret == -1)
	{
		perror("bind");
		return -1;
	}
	//启动监听
	int listen_is = listen(sc,10);
	if(listen_is == -1)
	{
		perror("listen");
		exit(1);
	}
	printf("监听已启动\n");
	struct sockaddr_in peer_addr;
	int peer_len = sizeof(peer_addr);

	//数据库连接
	MYSQL mysql;
    MYSQL *flag = NULL;
	//数据库初始化
    mysql_init(&mysql);
    flag = mysql_real_connect(&mysql,\
        "localhost","root","12345678",\
        "paccount",0,NULL,0);
    if (flag == NULL)
    {
        printf("mysql connect is error:%s",mysql_error(&mysql));
        exit(1);
    }else
    {
        printf("mysql connect is success\n");
    }
	//数据库信息读取存入temp
	char temp[1024] = {0};
	LEAVE leave;

	//接受数据包
	memset(&leave,0,sizeof(LEAVE));
	memset(&peer_addr,0,sizeof(peer_addr));
	//连接并接收数据包
	int client_sock = accept(sc,(struct sockaddr*)&peer_addr,&peer_len);
	printf("连接已经建立\n");
	printf("ip:%s,port:%d\n",inet_ntoa(peer_addr.sin_addr),\
		ntohs(peer_addr.sin_port));
	while(1)
	{
		memset(p,0,sizeof(p));
		//读取数据至p字符串
		int re = read(client_sock,p,1024);
		//解包
		unLeavePack(&leave);
		//请假申请
		if (strcmp(leave.type,"leavesubmit") == 0)
		{
			sprintf(temp,"insert into leaveinfo(name,leavetime,backtime,leavecause,\
				approval_status)values('%s','%s','%s','%s','%s')",leave.name,\
				leave.leavetime,leave.backtime,leave.leavecause,leave.approval_status);
			if(mysql_query(&mysql,temp) == 1)
			{
				printf("%s\n",mysql_error(&mysql));
				exit(1);
			}
		}
		//查看自己的历史请假信息
		if (strcmp(leave.type,"checkleavemyself") == 0)
		{
			ServeChecLeaveName(leave,mysql,client_sock);
		}
		//修改自己未被审批的请假信息
		if (strcmp(leave.type,"updateleavemyself") == 0)
		{
			UpdateLeaveMyself(leave,mysql,client_sock);
		}
		//审批员工的请假信息
		if (strcmp(leave.type,"approvalleave") == 0)
		{
			ServeApprovalLeave(mysql,client_sock);
		}
		//按照姓名查找员工的请假信息
		if (strcmp(leave.type,"cheakleavename") == 0)
		{
			ServeChecLeaveName(leave,mysql,client_sock);
		}
		//按照时间查找员工的请假信息
		if (strcmp(leave.type,"checkleavetime") == 0)
		{
			ServeChecLeaveTime(leave,mysql,client_sock);
		}
	}
	close(sc);
    return 0;
}
//解包请假
char * unLeavePack(LEAVE *leave)
{
	//将p中的字符串转为json对象
	cJSON* root = cJSON_Parse(p);
	//按照键获取json对象的值
	cJSON* type = cJSON_GetObjectItem(root,"type");
	cJSON* name = cJSON_GetObjectItem(root,"name");
	cJSON* leavetime = cJSON_GetObjectItem(root,"leavetime");
	cJSON* backtime = cJSON_GetObjectItem(root,"backtime");
	cJSON* leavecause = cJSON_GetObjectItem(root,"leavecause");
	cJSON* approval_status = cJSON_GetObjectItem(root,"approval_status");
	//将json对象的值获取对应类型的值
	strcpy(leave->type,cJSON_GetStringValue(type));
	strcpy(leave->name,cJSON_GetStringValue(name));
	strcpy(leave->leavetime,cJSON_GetStringValue(leavetime));
	strcpy(leave->backtime,cJSON_GetStringValue(backtime));
	strcpy(leave->leavecause,cJSON_GetStringValue(leavecause));
	strcpy(leave->approval_status,cJSON_GetStringValue(approval_status));
	//释放json对象
	cJSON_Delete(root);
}
//查询所有未审批的请假信息
void ServeApprovalLeave(MYSQL mysql,int client_sock)
{
	char temp[1024] = {0};
	LEAVE leave;
	MYSQL_RES *res = NULL;
    MYSQL_ROW row;
	sprintf(temp,"select * from leaveinfo where approval_status = 'wait'");
	if(mysql_query(&mysql,temp) == 1)
	{
		printf("%s\n",mysql_error(&mysql));
		exit(1);
	}
	//获得结果集
	res = mysql_store_result(&mysql);
	//显示所有数据
	for (int j = 0; j < mysql_num_rows(res); j++)
	{
		row = mysql_fetch_row(res);
		strcpy(leave.name,row[0]);
		strcpy(leave.leavetime,row[1]);
		memset(p,0,sizeof(p));
		for (int i = 0; i < mysql_num_fields(res); i++)
		{

			if(row[i]!=NULL)
			{
				strcat(p,row[i]);
				strcat(p,"\n");
			}
		}
		write(client_sock,p,strlen(p));
		read(client_sock,p,sizeof(p));
		if(strncmp(p,"leaveyes",8)==0)
		{
			sprintf(temp,"update leaveinfo set approval_status = 'yes' \
				where name = '%s' and leavetime = '%s'",leave.name,leave.leavetime);
			if(mysql_query(&mysql,temp) == 1)
			{
				printf("%s\n",mysql_error(&mysql));
				exit(1);
			}
		}
		if(strncmp(p,"leaveno",7)==0)
		{
			sprintf(temp,"update leaveinfo set approval_status = 'no' \
				where name = '%s' and leavetime = '%s'",leave.name,leave.leavetime);
			if(mysql_query(&mysql,temp) == 1)
			{
				printf("%s\n",mysql_error(&mysql));
				exit(1);
			}
		}
	}
	//发送结束信息quit给客户端
	if (mysql_num_rows(res) == 0)
	{
		write(client_sock,"nothing",7);
	}else
	{
		write(client_sock,"quit",4);
	}
}
//按姓名查询请假信息
int ServeChecLeaveName(LEAVE leave,MYSQL mysql,int client_sock)
{
	char temp[1024] = {0};
	MYSQL_RES *res = NULL;
    MYSQL_ROW row;
	sprintf(temp,"select * from leaveinfo where name = '%s'\
					",leave.name);
	if(mysql_query(&mysql,temp) == 1)
	{
		printf("%s\n",mysql_error(&mysql));
		exit(1);
	}
	//获得结果集
	res = mysql_store_result(&mysql);
	//显示所有数据
	for (int j = 0; j < mysql_num_rows(res); j++)
	{
		row = mysql_fetch_row(res);
		memset(p,0,sizeof(p));
		for (int i = 0; i < mysql_num_fields(res); i++)
		{
			if(row[i]!=NULL)
			{
				strcat(p,row[i]);
				strcat(p,"\t");
			}
		}
		strcat(p,"\n");
		//发送数据给客户端
		write(client_sock,p,strlen(p));
		//等待客户端回应信息isok
		while(1)
		{
			memset(p,0,sizeof(p));
			read(client_sock,p,1024);
			if (strcmp(p,"isok")==0)
			{
				break;
			}
		}
	}
	//发送结束信息quit给客户端
	if (mysql_num_rows(res) == 0)
	{
		write(client_sock,"nothing",7);
	}else
	{
		write(client_sock,"quit",4);
	}
}
//按时间查询请假信息
void ServeChecLeaveTime(LEAVE leave,MYSQL mysql,int client_sock)
{
	char temp[1024] = {0};
	MYSQL_RES *res = NULL;
    MYSQL_ROW row;
	sprintf(temp,"select * from leaveinfo where \
		leavetime = '%s'",leave.leavetime);
	if(mysql_query(&mysql,temp) == 1)
	{
		printf("%s\n",mysql_error(&mysql));
		exit(1);
	}
	//获得结果集
	res = mysql_store_result(&mysql);
	//显示所有数据
	for (int j = 0; j < mysql_num_rows(res); j++)
	{
		row = mysql_fetch_row(res);
		memset(p,0,sizeof(p));
		for (int i = 0; i < mysql_num_fields(res); i++)
		{
			if(row[i]!=NULL)
			{
				strcat(p,row[i]);
				strcat(p,"\t");
			}
		}
		strcat(p,"\n");
		//发送数据给客户端
		write(client_sock,p,strlen(p));
		//等待客户端回应信息isok
		while(1)
		{
			memset(p,0,sizeof(p));
			read(client_sock,p,1024);
			if (strcmp(p,"isok")==0)
			{
				break;
			}
		}
	}
	//发送结束信息quit给客户端
	if (mysql_num_rows(res) == 0)
	{
		write(client_sock,"nothing",7);
	}else
	{
		write(client_sock,"quit",4);
	}
}
//修改自己未被审批的请假信息
int UpdateLeaveMyself(LEAVE leave,MYSQL mysql,int client_sock)
{
	int flag = 1;
	char temp[1024] = {0};
	char x[100] = {0};
	char y[100] = {0};
	MYSQL_RES *res = NULL;
    MYSQL_ROW row;
	sprintf(temp,"select * from leaveinfo where approval_status = 'wait' \
		and name = '%s'",leave.name);
	if(mysql_query(&mysql,temp) == 1)
	{
		printf("%s\n",mysql_error(&mysql));
		exit(1);
	}
	//获得结果集
	res = mysql_store_result(&mysql);
	//显示所有数据
	for (int j = 0; j < mysql_num_rows(res); j++)
	{
		flag = 0;
		row = mysql_fetch_row(res);
		strcpy(y,row[0]);//暂存修改前请假姓名
		strcpy(x,row[1]);//暂存修改前请假时间
		memset(p,0,sizeof(p));
		for (int i = 0; i < mysql_num_fields(res); i++)
		{

			if(row[i]!=NULL)
			{
				strcat(p,row[i]);
				strcat(p,"\n");
			}
		}
		write(client_sock,p,strlen(p));
		memset(p,0,sizeof(p));
		read(client_sock,p,sizeof(p));
		//解包请假
		unLeavePack(&leave);
		//修改请假时间
		if (strncmp(leave.type,"updateleavetime",15)==0)
		{
			sprintf(temp,"update leaveinfo set leavetime = '%s' \
				where name = '%s' and leavetime = '%s'",\
				leave.leavetime,y,x);
			if(mysql_query(&mysql,temp) == 1)
			{
				printf("%s\n",mysql_error(&mysql));
				return -1;
			}
		}
		//修改请假返回时间
		if (strncmp(leave.type,"updatebacktime",14)==0)
		{
			sprintf(temp,"update leaveinfo set backtime = '%s' \
				where name = '%s' and leavetime = '%s'",\
				leave.backtime,y,x);
			if(mysql_query(&mysql,temp) == 1)
			{
				printf("%s\n",mysql_error(&mysql));
				return -1;
			}
		}
		//修改请假原因
		if (strncmp(leave.type,"updateleavecause",16)==0)
		{
			sprintf(temp,"update leaveinfo set leavecause = '%s' \
				where name = '%s' and leavetime = '%s'",\
				leave.leavecause,y,x);
			if(mysql_query(&mysql,temp) == 1)
			{
				printf("%s\n",mysql_error(&mysql));
				return -1;
			}
		}
	}
	if (flag == 1)
	{
		write(client_sock,"nothing",7);
	}else
	{
		write(client_sock,"quit",4);
	}
}